/*******************************************************************************
*
*   Copyright ©2009 Alexandru Marin
*
*   This file is part of nwave/pMRI C library.
*
*   This project started as an MSc degree project during a
*   stage at the Paris-Est university, under joint supervision of prof.
*   Bogdan Ionescu (Image Analysis and Processing Laboratory, "Politehica"
*   University of Bucharest), Caroline Chaux and Jean-Christophe Pesquet
*   (Laboratoire d'Informatique, Université Paris-Est, Institut Gaspard Monge).
*
*   nwave/pMRI C libray is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 2 of the License, or
*   (at your option) any later version.
*
*   nwave/pMRI C libray is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with nwave/pMRI C library.  If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/


#ifndef MRI_TYPES_H_
#define MRI_TYPES_H_

#include <complex.h>
#include <stdio.h>
#include "mri_utils.h"

/**
 * The following structure describes a 3D + t MRI image
 */
typedef struct {
	int height;
	int width;
	int nslices;
	int nsamples;
	complex float* data;
	mri_matrix_descriptor_t* desc;
} mri_image_t;

/**
 * Macro used to acces an image element by specifying its row, column
 * slice no. and sample no. It merely indexes the appropriate element
 * in the image data. Use it wisely (always thinking of what it translates to)
 */
#define MRI_IMAGE(image, row, col, slice, sample) image->data[\
(sample)*image->nslices*image->height*image->width + \
(slice)*image->height*image->width +\
(row)*image->width +\
(col)\
]

/**
 * Macro used to compute the size of an image (as total number of voxels * samples)
 */
#define MRI_IMAGE_SIZE(image) (image->nsamples*image->nslices*image->height*image->width)

/**
 * Reads an MRI image from given file f. The function expects a 2D/3D/3D+t
 * matrix as input.
 */
mri_image_t* mri_image_read(FILE* f);

/**
 * All functions followed by load/save are the same as their read/write
 * counterpart, just that instead of provifing an open stream one can provide
 * the name of the desired matrix (csv format is implied)
 */
mri_image_t* mri_image_load(char* name);

/**
 * Writes given image to file (in 3D+T format)
 */
void mri_image_write(mri_image_t* image, FILE* f);

void mri_image_save(mri_image_t* image, char* name);

/**
 * Writes a set of MRI images to file f, as a single matrix. The
 * last matrix dimension represents the number of images in the
 * image array
 */
void mri_images_write(int nimages, mri_image_t** images, FILE* f);

void mri_images_save(int nimages, mri_image_t** images, char* name);

/**
 * Returns a pointer to an allocated mri_image_t object initialized with the provided values
 */
mri_image_t* mri_image_alloc(int height, int width, int nslices, int nsamples);

/**
 * Returns a pointer to an allocated mri_image_t object initialized with the provided values
 * The actual image data is initialized with fillvalue
 */
mri_image_t* mri_image_gen_synth(int height, int width, int nslices, int nsamples, complex float fillvalue);

/**
 * Frees the memory occupied by image
 */
void mri_image_free(mri_image_t* image);


/**
 * The following structure describes a 3D MRI sensitivity matrix
 */
typedef struct {
	int height;
	int width;
	int ncoils;
	int nslices;
	complex float * data;
} mri_sens_t;

/**
 * Macro used to access an element of the sensitivity matrix sens
 * by specifying its row, column and slice no. It merely indexes the appropriate
 * element in the sensitivity data. Use it wisely (always thinking of what it translates to)
 */
#define MRI_SENS(sens, row, col, coil, slice) sens->data[\
(slice)*sens->ncoils*sens->height*sens->width +\
(coil)*sens->height*sens->width +\
(row)*sens->width +\
(col)\
]

/**
 * Macro used to compute the size of a sensitivity matrix
 */
#define MRI_SENS_SIZE(sens) (sens->nslices*sens->ncoils*sens->height*sens->width)

/**
 * Returns a pointer to an allocated mri_sens_t object initialized with the provided values
 */
mri_sens_t* mri_sens_alloc(int height, int width, int ncoils, int nslices);

/**
 * Returns a pointer to an allocated mri_sens_t object initialized with the provided values
 * The actual sensitivity data is initialized with fillvalue
 */
mri_sens_t* mri_sens_gen_synth(int height, int width, int ncoils, int nslices, complex float fillvalue);

/**
 * Reads a sensitivity matrix from given file f. The function expects a
 * width x height x ncoils matrix or a width x height x ncoils x nslices matrix
 */
mri_sens_t* mri_sens_read(FILE* f);

mri_sens_t* mri_sens_load(char* name);

/**
 * Frees the memory occupied by sens
 */
void mri_sens_free(mri_sens_t* sens);

#endif /* MRI_TYPES_H_ */
